from . import profile_blue
from info.utils.comments import login_required
from flask import g, redirect, render_template, jsonify, request, current_app, session
# 导入自定义状态码
from info.utils.response_code import RET
# 导入模型类
from info.models import User, Category, News
from info import db
# 导入七牛云扩展
from info.utils.image_storage import storage
from info import constants


@profile_blue.route('/info')
@login_required
def user_info():
    """
    1.尝试获取用户信息
    2.用户没有登录,重定向到项目首页重新登录
    3.用户登录就获取用户信息,加载模板,渲染数据
    :return:
    """
    user = g.user
    if not user:
        return redirect('/')
    data = {
        'user': user.to_dict()
    }
    # 渲染模板
    return render_template('news/user.html', data=data)


@profile_blue.route('/base_info', methods=['GET', 'POST'])
@login_required
def base_info():
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    if request.method == 'GET':
        data = {'user': user.to_dict()}
        return render_template('news/user_base_info.html', data=data)
    elif request.method == 'POST':
        # 获取参数,校验参数
        nick_name = request.json.get('nick_name')
        signature = request.json.get('signature')
        gender = request.json.get('gender')
        if not all([nick_name, signature, gender]):
            return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
        if gender not in ['MAN', 'WOMEN']:
            return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
        # try:
        #     user = User.query.filter_by(User.mobile == user.mobile).first()
        # except Exception as e:
        #     current_app.logger.error(e)
        #     return jsonify(errno=RET.DBERR, errmsg='数据库查询出错')
        # if not user:
        #     return jsonify(errno=RET.NODATA, errmsg='查询失败')
        user.nick_name = nick_name
        user.signature = signature
        # password属性封装了密码加密的方法，实现了密码的加密存储
        user.gender = gender
        # 提交数据到mysql数据库中
        try:
            db.session.add(user)
            db.session.commit()
        except Exception as e:
            current_app.logger.error(e)
            # 如果提交数据发生异常，需要进行回滚
            db.session.rollback()
            return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
        # 修改缓存中的昵称
        session['nick_name'] = nick_name
        return jsonify(errno=RET.OK, errmsg='保存成功')


@profile_blue.route('/pic_info', methods=['GET', 'POST'])
@login_required
def poc_info():
    """
    1.如果是get请求,需要加载模板文件(返回data,默认能看到头像)
    2.如果是post请求,获取参数,图片avatar
    3.校验参数
    4.七牛云需要传入二进制,所以要对avatar进行二进制化
    5.文件对象的判断,通过read,write方式进行判断
    6.保存七牛云返回的图片名称
    7.将图片名称存储在mysql数据库(相对路径更合适)
    8.提交数据,拼接绝对路径
    9.返回结果
    :return:
    """
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    # 判断请求方法如果为get请求，加载模板
    if request.method == 'GET':
        data = {
            'user': user.to_dict()
        }
        return render_template('news/user_pic_info.html', data=data)
    # 获取参数
    avatar = request.files.get('avatar')
    # 判断参数是否存在
    if not avatar:
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
    # 读取图片数据
    try:
        image_data = avatar.read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='数据错误')
    # 调用七牛云接口上传图片
    try:
        image_name = storage(image_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='上传图片异常')
    # 保存图片文件的名称到mysql数据库中
    user.avatar_url = image_name
    # 提交数据
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    # 拼接图片的绝对路径
    image_url = constants.QINIU_DOMIN_PREFIX + image_name
    # 返回图片的路径
    return jsonify(errno=RET.OK, errmsg='OK', data={'avatar_url': image_url})


@profile_blue.route('/pass_info', methods=['GET', 'POST'])
@login_required
def pass_info():
    """
    密码修改
    1、尝试获取用户信息，如果为get请求，加载模板
    2、获取参数
    3、检查参数的完整性
    4、判断旧密码是否正确
    5、更新密码
    6、提交数据
    7、返回结果

    :return:
    """
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    if request.method == 'GET':
        return render_template('news/user_pass_info.html')
    # 获取参数
    old_password = request.json.get("old_password")
    new_password = request.json.get("new_password")
    # 检查参数的完整性
    if not all([old_password, new_password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
    # 检查旧密码是否正确
    if not user.check_password(old_password):
        return jsonify(errno=RET.PWDERR, errmsg='密码错误')
    # 保存新密码,generate_password_hash
    user.password = new_password
    # 提交数据到数据库中
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    # 返回结果
    return jsonify(errno=RET.OK, errmsg='OK')


@profile_blue.route('/news_release', methods=['GET', 'POST'])
@login_required
def news_release():
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    if request.method == 'GET':
        try:
            categaries = Category.query.all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, ermsg='数据查询失败')
        if not categaries:
            return jsonify(errno=RET.NODATA, errmsg='没有数据')
        categary_list = []
        for categary in categaries:
            categary_list.append(categary.to_dict())
        categary_list.pop(0)
        data = {
            'categories': categary_list
        }
        return render_template('news/user_news_release.html', data=data)
    # 如果是POST请求
    """
    获取参数,校验参数完整性
    标题/分类/摘要/图片/内容   title/category_id/digest/index_image_url/content
    使用七牛云存储图片
    将数据保存到mysql数据库
    返回结果
    """
    title = request.form.get('title')
    category_id = request.form.get('category_id')
    digest = request.form.get('digest')
    index_image = request.files.get('index_image')
    content = request.form.get('content')
    if not all([title, category_id, digest, index_image, content]):
        return jsonify(errno=RET.DATAERR, errmsg='参数不完整')
    # 读取图片数据
    try:
        image_data = index_image.read()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg='数据错误')
    # 调用七牛云接口上传图片
    try:
        image_name = storage(image_data)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.THIRDERR, errmsg='上传图片异常')
    # 保存图片文件的名称到mysql数据库中
    new = News()
    new.title = title
    new.category_id = category_id
    new.digest = digest
    new.index_image_url = constants.QINIU_DOMIN_PREFIX + image_name
    new.content = content
    new.source = '个人发布'
    new.status = 0
    new.user_id = user.id
    # 提交数据
    try:
        db.session.add(new)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    return jsonify(errno=RET.OK, errmsg='OK')


@profile_blue.route('/news_list')
@login_required
def user_news_list():
    """
    用户新闻列表
    1、获取参数，页数p，默认1
    2、判断参数，整型
    3、获取用户信息，定义容器存储查询结果，总页数默认1，当前页默认1
    4、查询数据库，查询新闻数据并进行分页，
    5、获取总页数、当前页、新闻数据
    6、定义字典列表，遍历查询结果，添加到列表中
    7、返回模板news/user_news_list.html 'total_page',current_page,'news_dict_list'

    :return:
    """
    page = request.args.get('p', '1')
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
    user = g.user
    news_list = []
    total_page = 1
    current_page = 1
    try:
        paginate = News.query.filter(News.user_id == user.id).paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
        news_list = paginate.items
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据错误')
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_review_dict())
    data = {
        'news_list': news_dict_list,
        'total_page': total_page,
        'current_page': current_page
    }
    return render_template('news/user_news_list.html', data=data)


@profile_blue.route('/user_follow')
@login_required
def user_follow():
    """
    用户关注
    1、获取参数，页数p，默认1
    2、判断参数，整型
    3、获取用户信息，定义容器存储查询结果，总页数默认1，当前页默认1
    4、查询数据库，查询新闻数据并进行分页，user.followed.paginate
    5、获取总页数、当前页、新闻数据
    6、定义字典列表，遍历查询结果，添加到列表中
    7、返回模板news/user_follow.html, 'total_page',current_page,'users'

    :return:
    """
    page = request.args.get('p', '1')
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
    user = g.user
    follows = []
    current_page = 1
    total_page = 1
    try:
        paginate = user.followed.paginate(page, constants.USER_FOLLOWED_MAX_COUNT, False)
        current_page = paginate.page
        total_page = paginate.pages
        follows = paginate.items
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据错误')
    user_follow_list = []
    for follow in follows:
        user_follow_list.append(follow.to_dict())
    data = {
        'users': user_follow_list,
        'current_page': current_page,
        'total_page': total_page
    }
    return render_template('news/user_follow.html', data=data)


@profile_blue.route('/other_info')
@login_required
def other_info():
    """
    查询用户关注的其他用户信息
    1、获取用户登录信息
    2、获取参数，user_id
    3、校验参数，如果不存在404
    4、如果新闻有作者,并且登录用户关注过作者，is_followed = False
    5、返回模板news/other.html，is_followed,user,other_info
    :return:
    """
    user = g.user
    other_id = request.args.get('user_id')
    if not other_id:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    try:
        other = User.query.get(other_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据错误')
    if not other:
        return jsonify(errno=RET.NODATA, errmsg='无数据')
    is_follwed = False
    if other and user:
        if other in user.followed:
            is_follwed = True
    data = {
        'is_followed': is_follwed,
        'user': user.to_dict() if user else None,
        'other_info': other.to_dict()
    }
    return render_template('news/other.html', data=data)


@profile_blue.route('/other_news_list')
@login_required
def other_news_list():
    """
    返回指定用户发布的新闻
    1、获取参数，user_id，p默认1
    2、页数转成整型
    3、根据user_id查询用户表，判断查询结果
    4、如果用户存在，分页用户发布的新闻数据，other.news_list.paginate()
    5、获取分页数据，总页数、当前页
    6、遍历数据，转成字典
    7、返回结果，news_list,total_page,current_page
    :return:
    """
    user_id = request.args.get('user_id')
    page = request.args.get('p','1')
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    try:
        other = User.query.get(user_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据库错误')
    if not other:
        return jsonify(errno=RET.NODATA, errmsg='用户不存在')
    try:
        paginate = other.news_list.paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
        news_list = paginate.items
        current_page = paginate.page
        total_page = paginate.pages
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据错误')
    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_basic_dict())
    data = {
        'news_list': news_dict_list,
        'total_page': total_page,
        'current_page': current_page
    }
    return jsonify(errno=RET.OK, errmsg='OK', data=data)


@profile_blue.route('/collection')
@login_required
def user_collection():
    """
    用户收藏
    1、获取参数，页数p，默认1
    2、判断参数，整型
    3、获取用户信息，定义容器存储查询结果，总页数默认1，当前页默认1
    4、查询数据库，从用户收藏的的新闻中进行分页，user.collection_news
    5、获取总页数、当前页、新闻数据
    6、定义字典列表，遍历查询结果，添加到列表中
    7、返回模板news/user_collection.html,'total_page',current_page,'collections'

    :return:
    """
    page = request.args.get('p', '1')
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
    user = g.user
    news_list = []
    total_page = 1
    current_page = 1
    try:
        paginate = user.collection_news.paginate(page,constants.USER_COLLECTION_MAX_NEWS, False)
        current_page = paginate.page
        total_page = paginate.pages
        news_list = paginate.items
    except Exception as e:
        current_app.logger.error(e)

    news_dict_list = []
    for news in news_list:
        news_dict_list.append(news.to_basic_dict())
    data = {
        'collections': news_dict_list,
        'total_page': total_page,
        'current_page': current_page
    }

    return render_template('news/user_collection.html', data=data)


@profile_blue.route('/user_focus', methods=['POST'])
@login_required
def user_focus():
    """
    关注和取消关注
    1、尝试获取用户的信息
    2、如果未登录直接终止程序的执行
    3、获取参数，post请求的json数据，action和user_id
    4、检查参数，判断参数的完整性
    5、把user_id转成int类型
    6、判断action参数必须为focus或者focused；必须为关注/取消关注
    7、根据user_id查询数据库，
    8、判断查询结果是否存在
    9、判断用户选择的是关注还是取消关注
    10、返回结果
    :return:
    """
    # 尝试获取用户信息
    user_want = g.user
    # 判断用户信息是否存在
    if not user_want:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    # 获取post请求的参数
    user_id = request.json.get('user_id')
    action = request.json.get('action')
    # 判断参数的完整性
    if not all([user_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
    # 检查news_id参数的格式
    try:
        user_id = int(user_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数的格式错误')
    # 检查action参数
    if action not in ['focus', 'focused']:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 根据news_id查询mysql数据库
    try:
        user_to = User.query.get(user_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据异常')
    # 判断查询结果要关注的人是否存在
    if not user_to:
        return jsonify(errno=RET.NODATA, errmsg='新闻数据不存在')
    # 判断用户action选择的是收藏还是取消收藏
    if action == 'focus':
        # 判断用户之前未关注过该用户
        if user_to not in user_want.followed:
            user_want.followed.append(user_to)
    else:
        user_want.followed.remove(user_to)

    # 提交数据到数据库中
    try:
        db.session.add(user_want)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据异常')
    # 返回结果
    return jsonify(errno=RET.OK, errmsg='OK')
